/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			ETSheet.h
  \date			september 2011
  \author		TNick

  \brief		Contains the definition for ETSheet class


  Copyright (c) 2011, Nicu Tofan
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
 * Neither the name of the copyright holder nor the
   names of its contributors may be used to endorse or promote products
   derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL NICU TOFAN BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef __ETSHEET_INC__
#define __ETSHEET_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<main.h>

class		QDomDocument;

class		MdiChild;
class		ETI_CplxTxt;
class		ETI_MTxt;
class		ETSubItem;

#include	<QGraphicsScene>
#include	<QDomElement>

#include	<sheet/ETUndoHead.h>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/// Class representing logical root for all elements contained in a document (sheet)
/**
*	\section new_items Creating new documents
*	From this application's point of view, an instance of this clas is a
*	document. Documents are created either visible to the user (thus having a
*	MdiChild instance associated with them) using newVisible() or invisible to
*	the user using newInvisible(). Both functions accept an argument that
*	is either empty (QString::isEmpty() == true) or must represent a valid path
*	and file to be loaded. newVisible() shows error messages if something
*	wend wrong and returns NULL. newInvisible(), on the other hand, will
*	tell the error string in additional argument, while also returning NULL.
*
*	\section items_manag Managing the lists of documents
*	There are two lists of documents: visible and invisible ones, with two
*	sets of management functions.
*
*	Visible items may be enumerated using MainWindow's mdi area, thus no
*	storage is required by this class. One may get the number of opened
*	documents with visibleCount() and the document with a particular index
*	with visibleDoc().
*
*	Invisible documents are enumerated using internal (static) list.
*	To find out the number of invisible documents, simply use invisibleCount().
*	One may get a pointer to an invisible document using invisibleDoc().
*
*
*	\section loading_saving Loading a sheet from a XML file. Saving to a XML file.
*	As the name implies the XML format is used in
*	saving / loading the file and
*	<a href="http://doc.qt.nokia.com/latest/qtxml.html">QtXml Module</a>
*	is used to accomplish the task.
*
*	The format of the file that is saved follows the guidance in
*	<a href="https://code.google.com/p/equtemper/source/browse/trunk/doc/example.xml">
*	example.xml</a> that is located in
*	<a href="https://code.google.com/p/equtemper/source/browse/trunk/doc">doc</a>
*	subfolder. As a quick reference, the elements that are saved are:
*	- the tree of viewports / splits with their specific characteristics
*	- the list of ETI_CplxTxt items
*	- the list of ETI_MTxt items
*
*	The sheet exposes the loadXMLFile() function that needs a file name as
*	argument. It then attempts to read the file and make sence of it. A recursive
*	architecture is implemented, with each component having it's own (static) function
*	that handles it's loading from DOM tree. Specifically, the sheet's code
*	looks into viewport list and dispatches calls as appropriate, then
*	iterates the list of objects by type and creates them one by one.
*
*	The saving to a file is done using saveXMLFile(). Again, a file is expected
*	and, once it's available for writing, a DOM tree is constructed from the
*	content of the sheet and it is dumped to the file. The code manages
*	same tasks as in loading counterpart. As a rule of thumb, the container
*	is created by the caller and specific function is provided with
*	already created place where it should save it's content.
*
*	As a convenience, the class also implements saveQICommon() and loadQICommon()
*	to ease the task of saving / loading items that inherit from QGraphicsItem.
*	At this time only the position is saved.
*
*
*/
class ETSheet : public QGraphicsScene DDHC_INHERIT  		{
	DDHC_CLASS


	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

#define	XML_TAG_NAME		"name"

#define	XML_TAG_ROOT		"equtemper"
#define	XML_TAG_VP_LIST		"viewports"
#define	XML_TAG_VP_SPLIT	"viewport_split"
#define	XML_TAG_VP			"viewport"
#define	XML_TAG_ACTIVE		"active"
#define	XML_TAG_TRANSL		"translation"
#define	XML_TAG_X			"x"
#define	XML_TAG_Y			"y"
#define	XML_TAG_ROT			"rotation"
#define	XML_TAG_SCALE		"scale"
#define	XML_TAG_SPL_DATA	"split_data"
#define	XML_TAG_ORIENT		"orientation"
#define	XML_O_VERT			"vertical"
#define	XML_O_HORIZ			"horizontal"
#define	XML_TAG_ITEM		"item"
#define	XML_TAG_COMM		"common"
#define	XML_TAG_POS			"position"
#define	XML_TAG_CPLX_LIST	"complex_txt_list"
#define	XML_TAG_POS			"position"
#define	XML_TAG_SUBITEM		"sitem"
#define	XML_TAG_TYPE		"type"
#define	XML_TAG_FONT		"font"
#define	XML_TAG_COLOR		"color"
#define	XML_TAG_PEN			"pen"
#define	XML_TAG_NUMERATOR	"numerator"
#define	XML_TAG_DENOM		"denominator"
#define	XML_TAG_LIMIT		"limit"
#define	XML_TAG_FROM		"from"
#define	XML_TAG_CONTENT		"content"
#define	XML_TAG_CONTENT_D	"content_d"
#define	XML_TAG_BTM_LEFT	"bottom_left"
#define	XML_TAG_BTM_RIGHT	"bottom_right"
#define	XML_TAG_ROW			"row"
#define	XML_TAG_ORDER		"order"

#define	XML_TAG_FORM_LIST	"formatted_txt"
#define	XML_TAG_TEXT		"text"

#define XML_SIT_FRACT		"fract"
#define XML_SIT_HTEXT		"htext"
#define XML_SIT_INTEG		"integ"
#define XML_SIT_LIM			"lim"
#define XML_SIT_LOGICAC		"logicac"
#define XML_SIT_MATRIX		"matrix"
#define XML_SIT_RADIC		"radic"
#define XML_SIT_STEXT		"stext"
#define XML_SIT_SUM			"sum"
#define XML_SIT_ROOT		"root"
#define XML_SIT_ROWS		"rows"






	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

	private:


		/// list of invisible documents
		static QList<ETSheet*>		invisible_list;



	/// associated MDI panel
	MdiChild *					mdi_cont;


	/// undo / redo header
	ETUndoHead					hd_ur;


	/// current viewport
	ETSheetView *				vp_crt;


	/// the background color for this sheet
	QColor						back_col;



	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

private:

	/// constructor
	ETSheet		(QObject * parent = NULL);

public:
	/// destructor
	virtual				~ETSheet		( void );



	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Creating new documents
	*/
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */


	/// creates a new sheet; it is \b invisible to the user
	/**
 *	This function does not display error messages. Instead, when error
 * conditions are detected, corresponding string is returned in \b s_err
 * member.
 *
 *	@return	NULL for failure, newly created object otherwise
 */
	static ETSheet *	newInvisible	(
			QString			s_file,	/**< this may be empty, in which case
			a new empty structure is created, or may point to a file to load.*/
			QString *		s_err	/**< if the function returns NULL
		  (telling that it failed to open the file or to create a new one)
		  this string is populated by the error message */
			);


	/// creates a new sheet; it is \b visible to the user
	/**
 *	This function will display error messaegs to the user if it is unable
 * to perform requested opperation (create new or open file).
 *
 *	@return	NULL for failure, newly created object otherwise
 */
	static ETSheet *	newVisible	(
			QString			s_file,	/**< this may be empty, in which case
			a new empty structure is created, or may point to a file to load.*/
			MdiChild *		asoc_w	/**< pre-made MDI window that will host
		   this document */
			);


	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */





	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Managing the lists of documents
 */
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */


	/// tells the number of visible documents
	static int			visibleCount			( void );


	/// tells the number of invisible documents
	static int			invisibleCount			( void )
	{ return invisible_list.count();}


	/// get the visible document with index \b doc_index
	/**
 *	If the index is out of bounds, the function returns NULL, otherwise
 *	it returns the document that lies at thet particular index.
 */
	static ETSheet *	visibleDoc				(int doc_index);


	/// get the invisible document with index \b doc_index
	/**
 *	If the index is out of bounds, the function returns NULL, otherwise
 *	it returns the document that lies at thet particular index.
 */
	static ETSheet *	invisibleDoc			(int doc_index)
	{ return (doc_index >= invisible_list.count() ? NULL : invisible_list[doc_index]); }


	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */




	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Create new elements
 */
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

	/// create a new ETI_CplxTxt with one simple sub-item (ETSI_SText)
	ETI_CplxTxt *		addBasicCplx	(qreal new_x, qreal new_y);

	/// create a new ETI_CplxTxt with 3 simple sub-items (ETSI_SText), middle one being "="
	ETI_CplxTxt *		addCplx1Eq1		(qreal new_x, qreal new_y);

	/// create a new ETI_CplxTxt with 3 simple sub-items (ETSI_SText), middle one being "="
	ETI_MTxt *			addMText		(qreal new_x, qreal new_y);

	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */




	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Save and load	*/
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

private:

	/// is capable of loading an xml file
	static QDomDocument *	openXMLFile			(QString str_file_trg);




public:
	/// add the content of a xml file to current sheet
	void					loadXMLFile			(QString str_file_trg);


	/// save the content of current sheet to a xml file
	void					saveXMLFile			(QString str_file_trg);


	/// load common properties of a QGraphicsItem from a dox node
	static void				loadQICommon		(
			QGraphicsItem *	dest,
			QDomElement		dom_e
			);


	/// save common properties of a QGraphicsItem from a dox node
	static void				saveQICommon		(
			QGraphicsItem *	dest,
			QDomElement		dom_e
			);


	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */






	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Undo / redo support */
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */


	/// add a new undo item to this chain
	inline void			addUndoItem		(ETUndoElem* new_it)
	{ hd_ur.addUndoItem(new_it); }

	/// perform the undo action
	inline void			performUndo		( int cnt = 1 )
	{ hd_ur.performUndo(cnt); }

	/// perform the redo action
	inline void			performRedo		( int cnt = 1 )
	{ hd_ur.performRedo(cnt); }


	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */






	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Formatting */
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */


	/// add a new undo item to this chain
	void				slot_VP_ZoomIn		( void );


	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */







	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Viewports	and other GUI components */
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */


	/// get associated mdi window (NULL if none)
	inline MdiChild *		assocMDI			( void ) const
	{ return mdi_cont; }


	/// Remove all splits; Only a viewport remains
	void					vp_DelAll			( void );


	/// zoom in on current viewport
	void					vp_ZoomIn			( void );


	/// zoom out on current viewport
	void					vp_ZoomOut			( void );


	/// zoom extensions
	void					vp_ZoomExt			( void );


	/// zoom by window
	void					vp_ZoomWin			( void );





	/// rotate the view clockwise on current viewport
	void					vp_RotClk			( void );


	/// rotate the view counter-clockwise on current viewport
	void					vp_RotCtrClk		( void );


	/// informed about current viewport in window
	inline void				ackCurrentVp        ( ETSheetView * new_crt)
	{ vp_crt = new_crt; }


	/// tell which is current viewport (should never be null)
	inline ETSheetView *	currentVP			( void )
	{ return vp_crt; }


	/// tell which is current viewport (should never be null)
	void					setCurrentVp         ( ETSheetView * new_vp );


	/// gets the top vidget and tells if it's a viewport or splitter
	QWidget *				vp_TopWidget		(bool * b_is_viewport);


	/// the color used for active viewport's background
	inline QColor			background			(void)
	{ return back_col; }


	/// change the color used for active viewport's background
	void					setBackground		(QColor new_col);


	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */




	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
	/** @name Adjustments of apparence */
	//@{
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

	/// Allows changing the background color for selection
	void					changeBackCol		( void );


	/// Allows changing the color used to draw the text
	void					changeForeCol		( void );


	/// Allows changing the characteristics of the font
	void					changeFont			( void );


	/// Increases the size of the font
	void					incFontSize			( void );


	/// Decreases the size of the font
	void					decFontSize			( void );


	/// Removes specific formatting informations
	/**
	*	... informations about background color, text color and font;
	*	the item is left to inherit it's parent properties
	*/
	void					clearFormat			( void );



	/// Allows changing the background color for selection
	void					changeBackCol		( ETSubItem * s_it );


	/// Allows changing the color used to draw the text
	void					changeForeCol		( ETSubItem * s_it  );


	/// Allows changing the characteristics of the font
	void					changeFont			( ETSubItem * s_it  );


	/// Increases the size of the font
	void					incFontSize			( ETSubItem * s_it  );


	/// Decreases the size of the font
	void					decFontSize			( ETSubItem * s_it  );


	/// Removes specific formatting informations
	/**
	*	... informations about background color, text color and font;
	*	the item is left to inherit it's parent properties
	*/
	void					clearFormat			( ETSubItem * s_it  );


	/// Allows changing the background color for selection
	void					changeBackCol		( ETI_CplxTxt * it );


	/// Allows changing the color used to draw the text
	void					changeForeCol		( ETI_CplxTxt * it );


	/// Allows changing the characteristics of the font
	void					changeFont			( ETI_CplxTxt * it );


	/// Increases the size of the font
	void					incFontSize			( ETI_CplxTxt * it );


	/// Decreases the size of the font
	void					decFontSize			( ETI_CplxTxt * it );


	/// Removes specific formatting informations
	/**
	*	... informations about background color, text color and font;
	*	the item is left to inherit it's parent properties
	*/
	void					clearFormat			( ETI_CplxTxt * it  );

	//@}
	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */






	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class ETSheet	*/

/*  CLASS    =============================================================== */
//
//
//
//
#endif // __ETSHEET_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
